﻿namespace UnityEditor
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using UnityEngine;

    internal static class CurveUtility
    {
        private static Texture2D iconCurve;
        private static Texture2D iconKey;
        private static Texture2D iconNone;
        private const int kBrokenMask = 1;
        private const int kLeftTangentMask = 6;
        private const int kRightTangentMask = 0x18;
        private static Hashtable m_CombiRenderers = new Hashtable();
        private static Hashtable m_NormalRenderers = new Hashtable();

        public static void AddOrReplaceKey(CurveRenderer renderer, float time, float val, float beginTime, float endTime)
        {
            AnimationCurve curve = renderer.GetCurve();
            float num = 0f;
            float outTangent = 0f;
            TangentMode smooth = TangentMode.Smooth;
            TangentMode mode = TangentMode.Smooth;
            bool broken = false;
            bool flag2 = false;
            for (int i = curve.length - 1; i >= 0; i--)
            {
                Keyframe keyframe2 = curve[i];
                if (keyframe2.time >= beginTime)
                {
                    Keyframe keyframe3 = curve[i];
                    if (keyframe3.time < endTime)
                    {
                        if (!flag2)
                        {
                            Keyframe keyframe4 = curve[i];
                            outTangent = keyframe4.outTangent;
                            mode = GetKeyTangentMode(curve[i], 1);
                            flag2 = true;
                        }
                        Keyframe keyframe5 = curve[i];
                        num = keyframe5.inTangent;
                        smooth = GetKeyTangentMode(curve[i], 0);
                        if (GetKeyBroken(curve[i]))
                        {
                            broken = true;
                        }
                        curve.RemoveKey(i);
                    }
                }
            }
            float inTangent = renderer.EvaluateCurveDeltaSlow(time);
            Keyframe key = new Keyframe(time, val, inTangent, inTangent);
            int index = curve.AddKey(key);
            if (flag2)
            {
                if (!broken)
                {
                    if ((smooth == TangentMode.Editable) || (mode == TangentMode.Editable))
                    {
                        smooth = TangentMode.Editable;
                        mode = TangentMode.Editable;
                        key.inTangent = num;
                        key.outTangent = outTangent;
                        inTangent = CalculateSmoothTangent(key);
                        num = inTangent;
                        outTangent = inTangent;
                    }
                }
                else
                {
                    if (smooth == TangentMode.Smooth)
                    {
                        smooth = TangentMode.Editable;
                    }
                    if (mode == TangentMode.Smooth)
                    {
                        mode = TangentMode.Editable;
                    }
                }
                key.inTangent = num;
                key.outTangent = outTangent;
                SetKeyTangentMode(ref key, 0, smooth);
                SetKeyTangentMode(ref key, 1, mode);
                SetKeyBroken(ref key, broken);
                curve.MoveKey(index, key);
            }
            else
            {
                SetKeyModeFromContext(curve, index);
            }
            UpdateTangentsFromModeSurrounding(renderer, index);
        }

        public static float CalculateSmoothTangent(Keyframe key)
        {
            if (key.inTangent == float.PositiveInfinity)
            {
                key.inTangent = 0f;
            }
            if (key.outTangent == float.PositiveInfinity)
            {
                key.outTangent = 0f;
            }
            return ((key.outTangent + key.inTangent) * 0.5f);
        }

        public static void ClearCurveRendererCache()
        {
            m_CombiRenderers = new Hashtable();
            m_NormalRenderers = new Hashtable();
        }

        public static Color GetBalancedColor(Color c)
        {
            return new Color(0.15f + (0.75f * c.r), 0.2f + (0.6f * c.g), 0.1f + (0.9f * c.b));
        }

        public static string GetClipName(AnimationClip clip)
        {
            if (clip == null)
            {
                return "[No Clip]";
            }
            string name = clip.name;
            if ((clip.hideFlags & HideFlags.NotEditable) != 0)
            {
                name = name + " (Read-Only)";
            }
            return name;
        }

        public static int GetCurveGroupID(AnimationClip clip, AnimationClipCurveData curveData)
        {
            if (curveData.type != typeof(Transform))
            {
                return -1;
            }
            int num = (clip != null) ? clip.GetInstanceID() : 0;
            string str = curveData.propertyName.Substring(0, curveData.propertyName.Length - 1);
            return ((((num * 0x4c93) ^ (curveData.path.GetHashCode() * 0x2d9)) ^ (curveData.type.GetHashCode() * 0x1b)) ^ str.GetHashCode());
        }

        public static int GetCurveID(AnimationClip clip, AnimationClipCurveData curveData)
        {
            int num = (clip != null) ? clip.GetInstanceID() : 0;
            return ((((num * 0x4c93) ^ (curveData.path.GetHashCode() * 0x2d9)) ^ (curveData.type.GetHashCode() * 0x1b)) ^ curveData.propertyName.GetHashCode());
        }

        public static CurveRenderer GetCurveRenderer(AnimationClip clip, AnimationClipCurveData curveData)
        {
            if ((curveData.type == typeof(Transform)) && curveData.propertyName.StartsWith("localEulerAngles."))
            {
                int num;
                string str = curveData.propertyName.Substring(curveData.propertyName.Length - 1);
                if (str == "x")
                {
                    num = 0;
                }
                else if (str == "y")
                {
                    num = 1;
                }
                else if (str == "z")
                {
                    num = 2;
                }
                else
                {
                    num = -1;
                }
                string str2 = GetCurveGroupID(clip, curveData).ToString();
                EulerCurveCombinedRenderer renderer = (EulerCurveCombinedRenderer) m_CombiRenderers[str2];
                if (renderer == null)
                {
                    renderer = new EulerCurveCombinedRenderer(AnimationUtility.GetEditorCurve(clip, curveData.path, typeof(Transform), "m_LocalRotation.x"), AnimationUtility.GetEditorCurve(clip, curveData.path, typeof(Transform), "m_LocalRotation.y"), AnimationUtility.GetEditorCurve(clip, curveData.path, typeof(Transform), "m_LocalRotation.z"), AnimationUtility.GetEditorCurve(clip, curveData.path, typeof(Transform), "m_LocalRotation.w"), AnimationUtility.GetEditorCurve(clip, curveData.path, typeof(Transform), "localEulerAngles.x"), AnimationUtility.GetEditorCurve(clip, curveData.path, typeof(Transform), "localEulerAngles.y"), AnimationUtility.GetEditorCurve(clip, curveData.path, typeof(Transform), "localEulerAngles.z"));
                    m_CombiRenderers.Add(str2, renderer);
                }
                else if (renderer.QuaternionsDirty())
                {
                    renderer.SetQuaternions(AnimationUtility.GetEditorCurve(clip, curveData.path, typeof(Transform), "m_LocalRotation.x"), AnimationUtility.GetEditorCurve(clip, curveData.path, typeof(Transform), "m_LocalRotation.y"), AnimationUtility.GetEditorCurve(clip, curveData.path, typeof(Transform), "m_LocalRotation.z"), AnimationUtility.GetEditorCurve(clip, curveData.path, typeof(Transform), "m_LocalRotation.w"));
                }
                return new EulerCurveRenderer(num, renderer);
            }
            string key = GetCurveID(clip, curveData).ToString();
            NormalCurveRenderer renderer2 = (NormalCurveRenderer) m_NormalRenderers[key];
            if (renderer2 == null)
            {
                renderer2 = new NormalCurveRenderer(AnimationUtility.GetEditorCurve(clip, curveData.path, curveData.type, curveData.propertyName));
                m_NormalRenderers.Add(key, renderer2);
            }
            return renderer2;
        }

        public static bool GetFloatValue(GameObject root, string relativePath, System.Type type, string propertyName, out float data)
        {
            if ((type != typeof(Transform)) || !propertyName.StartsWith("localEulerAngles"))
            {
                return AnimationUtility.GetFloatValue(root, relativePath, type, propertyName, out data);
            }
            Transform transform = root.transform;
            if (relativePath != string.Empty)
            {
                transform = transform.Find(relativePath);
            }
            if (transform == null)
            {
                data = 0f;
                return false;
            }
            string str = propertyName.Substring(propertyName.Length - 1, 1);
            int num = !(str == "x") ? (!(str == "y") ? 2 : 1) : 0;
            data = transform.localEulerAngles[num];
            return true;
        }

        public static Texture2D GetIconCurve()
        {
            if (iconCurve == null)
            {
                iconCurve = EditorGUIUtility.LoadIcon("animationanimated");
            }
            return iconCurve;
        }

        public static Texture2D GetIconKey()
        {
            if (iconKey == null)
            {
                iconKey = EditorGUIUtility.LoadIcon("animationkeyframe");
            }
            return iconKey;
        }

        public static Texture2D GetIconNone()
        {
            if (iconNone == null)
            {
                iconNone = EditorGUIUtility.LoadIcon("animationnocurve");
            }
            return iconNone;
        }

        public static bool GetKeyBroken(Keyframe key)
        {
            return ((key.tangentMode & 1) != 0);
        }

        public static TangentMode GetKeyTangentMode(Keyframe key, int leftRight)
        {
            if (leftRight == 0)
            {
                return (TangentMode) ((key.tangentMode & 6) >> 1);
            }
            return (TangentMode) ((key.tangentMode & 0x18) >> 3);
        }

        public static int GetPathAndTypeID(string path, System.Type type)
        {
            return ((path.GetHashCode() * 0x1b) ^ type.GetHashCode());
        }

        public static Color GetPropertyColor(string name)
        {
            Color white = Color.white;
            int num = 0;
            if (name.StartsWith("m_LocalPosition"))
            {
                num = 1;
            }
            if (name.StartsWith("localEulerAngles"))
            {
                num = 2;
            }
            if (name.StartsWith("m_LocalScale"))
            {
                num = 3;
            }
            if (num == 1)
            {
                if (name.EndsWith(".x"))
                {
                    white = (Color) Handles.xAxisColor;
                }
                else if (name.EndsWith(".y"))
                {
                    white = (Color) Handles.yAxisColor;
                }
                else if (name.EndsWith(".z"))
                {
                    white = (Color) Handles.zAxisColor;
                }
            }
            else if (num == 2)
            {
                if (name.EndsWith(".x"))
                {
                    white = (Color) AnimationWindow.kEulerXColor;
                }
                else if (name.EndsWith(".y"))
                {
                    white = (Color) AnimationWindow.kEulerYColor;
                }
                else if (name.EndsWith(".z"))
                {
                    white = (Color) AnimationWindow.kEulerZColor;
                }
            }
            else if (num == 3)
            {
                if (name.EndsWith(".x"))
                {
                    white = GetBalancedColor(new Color(0.7f, 0.4f, 0.4f));
                }
                else if (name.EndsWith(".y"))
                {
                    white = GetBalancedColor(new Color(0.4f, 0.7f, 0.4f));
                }
                else if (name.EndsWith(".z"))
                {
                    white = GetBalancedColor(new Color(0.4f, 0.4f, 0.7f));
                }
            }
            else if (name.EndsWith(".x"))
            {
                white = (Color) Handles.xAxisColor;
            }
            else if (name.EndsWith(".y"))
            {
                white = (Color) Handles.yAxisColor;
            }
            else if (name.EndsWith(".z"))
            {
                white = (Color) Handles.zAxisColor;
            }
            else if (name.EndsWith(".w"))
            {
                white = new Color(1f, 0.5f, 0f);
            }
            else if (name.EndsWith(".r"))
            {
                white = GetBalancedColor(Color.red);
            }
            else if (name.EndsWith(".g"))
            {
                white = GetBalancedColor(Color.green);
            }
            else if (name.EndsWith(".b"))
            {
                white = GetBalancedColor(Color.blue);
            }
            else if (name.EndsWith(".a"))
            {
                white = GetBalancedColor(Color.yellow);
            }
            else if (name.EndsWith(".width"))
            {
                white = GetBalancedColor(Color.blue);
            }
            else if (name.EndsWith(".height"))
            {
                white = GetBalancedColor(Color.yellow);
            }
            else
            {
                float f = 6.283185f * (name.GetHashCode() % 0x3e8);
                f -= Mathf.Floor(f);
                white = GetBalancedColor(EditorGUIUtility.HSVToRGB(f, 1f, 1f));
            }
            white.a = 1f;
            return white;
        }

        public static string GetPropertyName(string name)
        {
            if (name.StartsWith("["))
            {
                name = name.Substring(name.IndexOf("]") + 2);
            }
            name = ObjectNames.NicifyVariableName(name);
            return name;
        }

        public static bool HaveKeysInRange(AnimationCurve curve, float beginTime, float endTime)
        {
            for (int i = curve.length - 1; i >= 0; i--)
            {
                Keyframe keyframe = curve[i];
                if (keyframe.time >= beginTime)
                {
                    Keyframe keyframe2 = curve[i];
                    if (keyframe2.time < endTime)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        public static void RemoveKeysInRange(AnimationCurve curve, float beginTime, float endTime)
        {
            for (int i = curve.length - 1; i >= 0; i--)
            {
                Keyframe keyframe = curve[i];
                if (keyframe.time >= beginTime)
                {
                    Keyframe keyframe2 = curve[i];
                    if (keyframe2.time < endTime)
                    {
                        curve.RemoveKey(i);
                    }
                }
            }
        }

        public static void SetKeyBroken(ref Keyframe key, bool broken)
        {
            if (broken)
            {
                key.tangentMode |= 1;
            }
            else
            {
                key.tangentMode &= -2;
            }
        }

        public static void SetKeyModeFromContext(AnimationCurve curve, int keyIndex)
        {
            Keyframe key = curve[keyIndex];
            bool broken = false;
            if ((keyIndex > 0) && GetKeyBroken(curve[keyIndex - 1]))
            {
                broken = true;
            }
            if ((keyIndex < (curve.length - 1)) && GetKeyBroken(curve[keyIndex + 1]))
            {
                broken = true;
            }
            SetKeyBroken(ref key, broken);
            if (broken)
            {
                if (keyIndex > 0)
                {
                    SetKeyTangentMode(ref key, 0, GetKeyTangentMode(curve[keyIndex - 1], 1));
                }
                if (keyIndex < (curve.length - 1))
                {
                    SetKeyTangentMode(ref key, 1, GetKeyTangentMode(curve[keyIndex + 1], 0));
                }
            }
            else
            {
                TangentMode smooth = TangentMode.Smooth;
                if ((keyIndex > 0) && (GetKeyTangentMode(curve[keyIndex - 1], 1) != TangentMode.Smooth))
                {
                    smooth = TangentMode.Editable;
                }
                if ((keyIndex < (curve.length - 1)) && (GetKeyTangentMode(curve[keyIndex + 1], 0) != TangentMode.Smooth))
                {
                    smooth = TangentMode.Editable;
                }
                SetKeyTangentMode(ref key, 0, smooth);
                SetKeyTangentMode(ref key, 1, smooth);
            }
            curve.MoveKey(keyIndex, key);
        }

        public static void SetKeyTangentMode(ref Keyframe key, int leftRight, TangentMode mode)
        {
            if (leftRight == 0)
            {
                key.tangentMode &= -7;
                key.tangentMode |= ((int) mode) << 1;
            }
            else
            {
                key.tangentMode &= -25;
                key.tangentMode |= ((int) mode) << 3;
            }
            if (GetKeyTangentMode(key, leftRight) != mode)
            {
                Debug.Log("bug");
            }
        }

        public static void SyncCurves(CurveRenderer[] renderers)
        {
            List<Keyframe> list = new List<Keyframe>();
            for (int i = 0; i < renderers.Length; i++)
            {
                Keyframe[] keys = renderers[i].GetCurve().keys;
                for (int m = 0; m < keys.Length; m++)
                {
                    list.Add(keys[m]);
                }
            }
            list.Sort(new KeyframeComparer());
            for (int j = list.Count - 1; j > 0; j--)
            {
                Keyframe key = list[j - 1];
                Keyframe keyframe2 = list[j];
                if (Mathf.Approximately(key.time, keyframe2.time))
                {
                    if (GetKeyBroken(key) != GetKeyBroken(keyframe2))
                    {
                        SetKeyBroken(ref key, true);
                    }
                    if (GetKeyTangentMode(key, 0) != GetKeyTangentMode(keyframe2, 0))
                    {
                        SetKeyTangentMode(ref key, 0, TangentMode.Editable);
                    }
                    if (GetKeyTangentMode(key, 1) != GetKeyTangentMode(keyframe2, 1))
                    {
                        SetKeyTangentMode(ref key, 1, TangentMode.Editable);
                    }
                    list[j - 1] = key;
                    list.RemoveAt(j);
                }
            }
            for (int k = 0; k < renderers.Length; k++)
            {
                AnimationCurve curve = renderers[k].GetCurve();
                for (int n = 0; n < list.Count; n++)
                {
                    int index = n;
                    Keyframe keyframe3 = list[n];
                    Keyframe keyframe6 = curve[index];
                    if (Mathf.Approximately(keyframe6.time, keyframe3.time))
                    {
                        Keyframe keyframe4 = curve[index];
                        SetKeyBroken(ref keyframe4, GetKeyBroken(keyframe3));
                        SetKeyTangentMode(ref keyframe4, 0, GetKeyTangentMode(keyframe3, 0));
                        SetKeyTangentMode(ref keyframe4, 1, GetKeyTangentMode(keyframe3, 1));
                        curve.MoveKey(index, keyframe4);
                    }
                    else
                    {
                        float time = keyframe3.time;
                        float num8 = renderers[k].EvaluateCurveSlow(time);
                        float inTangent = renderers[k].EvaluateCurveDeltaSlow(time);
                        Keyframe keyframe5 = new Keyframe(time, num8, inTangent, inTangent);
                        SetKeyBroken(ref keyframe5, GetKeyBroken(keyframe3));
                        SetKeyTangentMode(ref keyframe5, 0, GetKeyTangentMode(keyframe3, 0));
                        SetKeyTangentMode(ref keyframe5, 1, GetKeyTangentMode(keyframe3, 1));
                        curve.AddKey(keyframe5);
                    }
                }
            }
        }

        public static void UpdateAllTangentsFromMode(CurveRenderer renderer)
        {
            AnimationCurve curve = renderer.GetCurve();
            for (int i = 0; i < curve.length; i++)
            {
                UpdateTangentsFromMode(renderer, i);
            }
        }

        public static void UpdateTangentsFromMode(CurveRenderer renderer, int index)
        {
            AnimationCurve curve = renderer.GetCurve();
            if ((index >= 0) && (index < curve.length))
            {
                Keyframe key = curve[index];
                if ((GetKeyTangentMode(key, 0) == TangentMode.Linear) && (index >= 1))
                {
                    key.inTangent = renderer.CalculateLinearTangent(index, index - 1);
                }
                if ((GetKeyTangentMode(key, 1) == TangentMode.Linear) && ((index + 1) < curve.length))
                {
                    key.outTangent = renderer.CalculateLinearTangent(index, index + 1);
                }
                if ((GetKeyTangentMode(key, 0) == TangentMode.Smooth) || (GetKeyTangentMode(key, 1) == TangentMode.Smooth))
                {
                    float num = renderer.CalculateSmoothTangent(index);
                    key.inTangent = num;
                    key.outTangent = num;
                }
                curve.MoveKey(index, key);
            }
        }

        public static void UpdateTangentsFromModeSurrounding(CurveRenderer renderer, int index)
        {
            UpdateTangentsFromMode(renderer, index - 2);
            UpdateTangentsFromMode(renderer, index - 1);
            UpdateTangentsFromMode(renderer, index);
            UpdateTangentsFromMode(renderer, index + 1);
            UpdateTangentsFromMode(renderer, index + 2);
        }

        public class KeyframeComparer : IComparer<Keyframe>
        {
            int IComparer<Keyframe>.Compare(Keyframe x, Keyframe y)
            {
                float time = x.time;
                float num2 = y.time;
                if (time != num2)
                {
                    return (int) Mathf.Sign(time - num2);
                }
                return 0;
            }
        }
    }
}

